{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|default_exp models.MINIROCKET"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MINIROCKET"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">A Very Fast (Almost) Deterministic Transform for Time Series Classification."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "import sklearn\n",
    "from sklearn.ensemble import VotingClassifier, VotingRegressor\n",
    "from sklearn.linear_model import RidgeClassifierCV, RidgeCV\n",
    "from sklearn.metrics import make_scorer\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "from tsai.data.external import *\n",
    "from tsai.imports import *\n",
    "from tsai.models.layers import *\n",
    "from tsai.utils import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "class MiniRocketClassifier(sklearn.pipeline.Pipeline):\n",
    "    \"\"\"Time series classification using MINIROCKET features and a linear classifier\"\"\"\n",
    "    def __init__(self, num_features=10_000, max_dilations_per_kernel=32, random_state=None,\n",
    "                 alphas=np.logspace(-3, 3, 7), normalize_features=True, memory=None, verbose=False, scoring=None, class_weight=None, **kwargs):\n",
    "        \"\"\" MiniRocketClassifier is recommended for up to 10k time series. \n",
    "        \n",
    "        For a larger dataset, you can use MINIROCKET (in Pytorch).\n",
    "        scoring = None --> defaults to accuracy.\n",
    "        \"\"\"\n",
    "        \n",
    "        try: \n",
    "            import sktime\n",
    "            from sktime.transformations.panel.rocket._minirocket_multivariate import MiniRocketMultivariate\n",
    "        except ImportError: \n",
    "            raise ImportError(\"You need to install sktime to be able to use MiniRocketClassifier\")\n",
    "            \n",
    "        self.steps = [('minirocketmultivariate', MiniRocketMultivariate(num_kernels=num_features, \n",
    "                                                                        max_dilations_per_kernel=max_dilations_per_kernel,\n",
    "                                                                        random_state=random_state))]\n",
    "        if normalize_features:\n",
    "            self.steps += [('scalar', StandardScaler(with_mean=False))]\n",
    "        \n",
    "        self.steps += [('ridgeclassifiercv', RidgeClassifierCV(alphas=alphas, \n",
    "                                                              scoring=scoring, \n",
    "                                                              class_weight=class_weight, \n",
    "                                                              **kwargs))]\n",
    "        store_attr()\n",
    "        self._validate_steps()\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'Pipeline(steps={self.steps.copy()})'\n",
    "\n",
    "    def save(self, fname=None, path='./models'):\n",
    "        fname = ifnone(fname, 'MiniRocketClassifier')\n",
    "        path = Path(path)\n",
    "        filename = path/fname\n",
    "        filename.parent.mkdir(parents=True, exist_ok=True)\n",
    "        with open(f'{filename}.pkl', 'wb') as output:\n",
    "            pickle.dump(self, output, pickle.HIGHEST_PROTOCOL)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def load_minirocket(fname, path='./models'):\n",
    "    path = Path(path)\n",
    "    filename = path/fname\n",
    "    with open(f'{filename}.pkl', 'rb') as input:\n",
    "        output = pickle.load(input)\n",
    "    return output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "class MiniRocketRegressor(sklearn.pipeline.Pipeline):\n",
    "    \"\"\"Time series regression using MINIROCKET features and a linear regressor\"\"\"\n",
    "    def __init__(self, num_features=10000, max_dilations_per_kernel=32, random_state=None,\n",
    "                 alphas=np.logspace(-3, 3, 7), *, normalize_features=True, memory=None, verbose=False, scoring=None, **kwargs):\n",
    "        \"\"\" MiniRocketRegressor is recommended for up to 10k time series. \n",
    "        \n",
    "        For a larger dataset, you can use MINIROCKET (in Pytorch).\n",
    "        scoring = None --> defaults to r2.\n",
    "        \"\"\"\n",
    "        \n",
    "        try: \n",
    "            import sktime\n",
    "            from sktime.transformations.panel.rocket._minirocket_multivariate import MiniRocketMultivariate\n",
    "        except ImportError: \n",
    "            raise ImportError(\"You need to install sktime to be able to use MiniRocketRegressor\")\n",
    "            \n",
    "        self.steps = [('minirocketmultivariate', MiniRocketMultivariate(num_kernels=num_features,\n",
    "                                                                        max_dilations_per_kernel=max_dilations_per_kernel,\n",
    "                                                                        random_state=random_state))]\n",
    "        if normalize_features:\n",
    "            self.steps += [('scalar', StandardScaler(with_mean=False))]\n",
    "        \n",
    "        self.steps += [('ridgecv', RidgeCV(alphas=alphas, scoring=scoring, **kwargs))]\n",
    "        store_attr()\n",
    "        self._validate_steps()\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'Pipeline(steps={self.steps.copy()})'\n",
    "\n",
    "    def save(self, fname=None, path='./models'):\n",
    "        fname = ifnone(fname, 'MiniRocketRegressor')\n",
    "        path = Path(path)\n",
    "        filename = path/fname\n",
    "        filename.parent.mkdir(parents=True, exist_ok=True)\n",
    "        with open(f'{filename}.pkl', 'wb') as output:\n",
    "            pickle.dump(self, output, pickle.HIGHEST_PROTOCOL)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def load_minirocket(fname, path='./models'):\n",
    "    path = Path(path)\n",
    "    filename = path/fname\n",
    "    with open(f'{filename}.pkl', 'rb') as input:\n",
    "        output = pickle.load(input)\n",
    "    return output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "class MiniRocketVotingClassifier(VotingClassifier):\n",
    "    \"\"\"Time series classification ensemble using MINIROCKET features, a linear classifier and majority voting\"\"\"\n",
    "    def __init__(self, n_estimators=5, weights=None, n_jobs=-1, num_features=10_000, max_dilations_per_kernel=32, random_state=None, \n",
    "                 alphas=np.logspace(-3, 3, 7), normalize_features=True, memory=None, verbose=False, scoring=None, class_weight=None, **kwargs):\n",
    "        store_attr()\n",
    "        \n",
    "        try: \n",
    "            import sktime\n",
    "        except ImportError: \n",
    "            raise ImportError(\"You need to install sktime to be able to use MiniRocketVotingClassifier\")\n",
    "            \n",
    "        estimators = [(f'est_{i}', MiniRocketClassifier(num_features=num_features, max_dilations_per_kernel=max_dilations_per_kernel, \n",
    "                                                       random_state=random_state, alphas=alphas, normalize_features=normalize_features, memory=memory, \n",
    "                                                       verbose=verbose, scoring=scoring, class_weight=class_weight, **kwargs)) \n",
    "                    for i in range(n_estimators)]\n",
    "        super().__init__(estimators, voting='hard', weights=weights, n_jobs=n_jobs, verbose=verbose)\n",
    "\n",
    "    def __repr__(self):   \n",
    "        return f'MiniRocketVotingClassifier(n_estimators={self.n_estimators}, \\nsteps={self.estimators[0][1].steps})'\n",
    "\n",
    "    def save(self, fname=None, path='./models'):\n",
    "        fname = ifnone(fname, 'MiniRocketVotingClassifier')\n",
    "        path = Path(path)\n",
    "        filename = path/fname\n",
    "        filename.parent.mkdir(parents=True, exist_ok=True)\n",
    "        with open(f'{filename}.pkl', 'wb') as output:\n",
    "            pickle.dump(self, output, pickle.HIGHEST_PROTOCOL)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def get_minirocket_preds(X, fname, path='./models', model=None):\n",
    "    if X.ndim == 1: X = X[np.newaxis][np.newaxis]\n",
    "    elif X.ndim == 2: X = X[np.newaxis]\n",
    "    if model is None: \n",
    "        model = load_minirocket(fname=fname, path=path)\n",
    "    return model.predict(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "class MiniRocketVotingRegressor(VotingRegressor):\n",
    "    \"\"\"Time series regression ensemble using MINIROCKET features, a linear regressor and a voting regressor\"\"\"\n",
    "    def __init__(self, n_estimators=5, weights=None, n_jobs=-1, num_features=10_000, max_dilations_per_kernel=32, random_state=None,\n",
    "                 alphas=np.logspace(-3, 3, 7), normalize_features=True, memory=None, verbose=False, scoring=None, **kwargs):\n",
    "        store_attr()\n",
    "        \n",
    "        try: \n",
    "            import sktime\n",
    "        except ImportError: \n",
    "            raise ImportError(\"You need to install sktime to be able to use MiniRocketVotingRegressor\")\n",
    "            \n",
    "        estimators = [(f'est_{i}', MiniRocketRegressor(num_features=num_features, max_dilations_per_kernel=max_dilations_per_kernel,\n",
    "                                                      random_state=random_state, alphas=alphas, normalize_features=normalize_features, memory=memory,\n",
    "                                                      verbose=verbose, scoring=scoring, **kwargs))\n",
    "                      for i in range(n_estimators)]\n",
    "        super().__init__(estimators, weights=weights, n_jobs=n_jobs, verbose=verbose)\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f'MiniRocketVotingRegressor(n_estimators={self.n_estimators}, \\nsteps={self.estimators[0][1].steps})'\n",
    "\n",
    "    def save(self, fname=None, path='./models'):\n",
    "        fname = ifnone(fname, 'MiniRocketVotingRegressor')\n",
    "        path = Path(path)\n",
    "        filename = path/fname\n",
    "        filename.parent.mkdir(parents=True, exist_ok=True)\n",
    "        with open(f'{filename}.pkl', 'wb') as output:\n",
    "            pickle.dump(self, output, pickle.HIGHEST_PROTOCOL)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n"
     ]
    }
   ],
   "source": [
    "#|extras\n",
    "# Univariate classification with sklearn-type API\n",
    "dsid = 'OliveOil'\n",
    "fname = 'MiniRocketClassifier'\n",
    "X_train, y_train, X_test, y_test = get_UCR_data(dsid)\n",
    "cls = MiniRocketClassifier()\n",
    "cls.fit(X_train, y_train)\n",
    "cls.save(fname)\n",
    "pred = cls.score(X_test, y_test)\n",
    "del cls\n",
    "cls = load_minirocket(fname)\n",
    "test_eq(cls.score(X_test, y_test), pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9277777777777778"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#|extras\n",
    "# Multivariate classification with sklearn-type API\n",
    "dsid = 'NATOPS'\n",
    "X_train, y_train, X_test, y_test = get_UCR_data(dsid)\n",
    "cls = MiniRocketClassifier()\n",
    "cls.fit(X_train, y_train)\n",
    "cls.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n",
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n",
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n",
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n",
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.9166666666666666"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#|extras\n",
    "# Multivariate classification with sklearn-type API\n",
    "dsid = 'NATOPS'\n",
    "X_train, y_train, X_test, y_test = get_UCR_data(dsid)\n",
    "cls = MiniRocketVotingClassifier(5)\n",
    "cls.fit(X_train, y_train)\n",
    "cls.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import mean_squared_error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.04099244037606886\n"
     ]
    }
   ],
   "source": [
    "#|extras\n",
    "# Univariate regression with sklearn-type API\n",
    "dsid = 'Covid3Month'\n",
    "fname = 'MiniRocketRegressor'\n",
    "X_train, y_train, X_test, y_test = get_Monash_regression_data(dsid)\n",
    "if X_train is not None:\n",
    "    rmse_scorer = make_scorer(mean_squared_error, greater_is_better=False)\n",
    "    reg = MiniRocketRegressor(scoring=rmse_scorer)\n",
    "    reg.fit(X_train, y_train)\n",
    "    reg.save(fname)\n",
    "    del reg\n",
    "    reg = load_minirocket(fname)\n",
    "    y_pred = reg.predict(X_test)\n",
    "    print(mean_squared_error(y_test, y_pred, squared=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.2938026879322577\n"
     ]
    }
   ],
   "source": [
    "#|extras\n",
    "# Multivariate regression with sklearn-type API\n",
    "dsid = 'AppliancesEnergy'\n",
    "X_train, y_train, X_test, y_test = get_Monash_regression_data(dsid)\n",
    "if X_train is not None:\n",
    "    rmse_scorer = make_scorer(mean_squared_error, greater_is_better=False)\n",
    "    reg = MiniRocketRegressor(scoring=rmse_scorer)\n",
    "    reg.fit(X_train, y_train)\n",
    "    reg.save(fname)\n",
    "    del reg\n",
    "    reg = load_minirocket(fname)\n",
    "    y_pred = reg.predict(X_test)\n",
    "    print(mean_squared_error(y_test, y_pred, squared=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n",
      "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.286295546348893\n"
     ]
    }
   ],
   "source": [
    "#|extras\n",
    "# Multivariate regression ensemble with sklearn-type API\n",
    "if X_train is not None:\n",
    "    reg = MiniRocketVotingRegressor(5, scoring=rmse_scorer)\n",
    "    reg.fit(X_train, y_train)\n",
    "    y_pred = reg.predict(X_test)\n",
    "    print(mean_squared_error(y_test, y_pred, squared=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": "IPython.notebook.save_checkpoint();",
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/nacho/notebooks/tsai/nbs/055_models.MINIROCKET.ipynb saved at 2023-04-01 19:16:32\n",
      "Correct notebook to script conversion! 😃\n",
      "Saturday 01/04/23 19:16:36 CEST\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "                <audio  controls=\"controls\" autoplay=\"autoplay\">\n",
       "                    <source src=\"data:audio/wav;base64,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\" type=\"audio/wav\" />\n",
       "                    Your browser does not support the audio element.\n",
       "                </audio>\n",
       "              "
      ],
      "text/plain": [
       "<IPython.lib.display.Audio object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#|eval: false\n",
    "#|hide\n",
    "from tsai.export import get_nb_name; nb_name = get_nb_name(locals())\n",
    "from tsai.imports import create_scripts; create_scripts(nb_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
